package service

import (
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
	"strconv"
	"sync"
	"wechat/basic/config"
	"wechat/handler/model"
	"wechat/handler/request"
)

var (
	upgrader = websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
	}
	clients = map[string]*Node{}
	mu      sync.Mutex
)

type Node struct {
	UserId string
	Conn   *websocket.Conn
	Data   chan []byte
}

func Chat(c *gin.Context) {
	userId := c.Query("userId")
	friendId := c.Query("friendId")
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		return
	}
	mu.Lock()
	clients[userId] = &Node{
		UserId: userId,
		Conn:   conn,
		Data:   make(chan []byte, 100),
	}
	mu.Unlock()
	go func() {
		rab := NewRabbitMQSimple("user." + userId)
		defer rab.Destory()
		rab.ConsumeSimple(clients[userId])
	}()
	go ReceiverMsg(clients[userId], friendId)
	go SenderMsg(clients[userId])
}
func ReceiverMsg(myNode *Node, friendId string) {
	defer func() {
		mu.Lock()
		delete(clients, myNode.UserId)
		myNode.Conn.Close()
		close(myNode.Data)
		mu.Unlock()
	}()
	uid, _ := strconv.Atoi(myNode.UserId)
	fid, _ := strconv.Atoi(friendId)
	var friend model.Friend
	if err := friend.IsFriend(config.DB, uid, fid); err != nil {
		log.Printf("好友关系不存在")
		return
	}
	var black model.Black
	if err := black.IsBlack(config.DB, uid, fid); err == nil {
		log.Printf("已存在黑名单")
		return
	}
	rab := NewRabbitMQSimple("user." + friendId)
	defer rab.Destory()
	for {
		_, data, err := myNode.Conn.ReadMessage()
		if err != nil {
			return
		}
		message := model.Message{
			UserId:   uid,
			FriendId: fid,
			Content:  string(data),
		}
		err = message.AddMessage(config.DB)
		if err != nil {
			log.Printf("消息存储失败")
			return
		}
		mu.Lock()
		friendNode, ok := clients[friendId]
		mu.Unlock()
		if ok {
			select {
			case friendNode.Data <- data:
			default:
				log.Printf("好友消息已满,RabbitMq发送消息")
				rab.PublishSimple(string(data))
			}
		} else {
			log.Printf("好友离线状态,RabbitMq发送消息")
			rab.PublishSimple(string(data))
		}
	}
}

func SenderMsg(myNode *Node) {
	for {
		select {
		case data := <-myNode.Data:
			err := myNode.Conn.WriteMessage(websocket.TextMessage, data)
			if err != nil {
				return
			}
		}
	}
}

func GetMessage(c *gin.Context) {
	var form request.GetMessage
	if err := c.ShouldBind(&form); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 400, "msg": "参数错误"})
		return
	}
	var message model.Message
	list, err := message.GetMessage(config.DB, form.UserId, form.FriendId)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 400, "msg": "查询聊天记录失败"})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "查询聊天记录成功",
		"data": gin.H{
			"list": list,
		},
	})
	return
}
